package org.springframework.social.slideshare.api.impl;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.social.slideshare.api.SlideShare;
import org.springframework.social.slideshare.api.SlideshowOperations;
import org.springframework.social.slideshare.api.impl.xml.JacksonUtils;
import org.springframework.social.support.ClientHttpRequestFactorySelector;
import org.springframework.social.support.HttpRequestDecorator;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* This is the central class to interact with SlideShare.
*
* @author Tadaya Tsuyukubo
*/
// since SlideShare doesn't use OAuth, not extending any abstract class from spring-social-core
public class SlideShareTemplate implements SlideShare {
private static final Log logger = LogFactory.getLog(SlideShareTemplate.class);
private final RestTemplate restTemplate;
private SlideshowOperations slideshowOperations;
public SlideShareTemplate(String apiKey, String sharedSecret) {
this.restTemplate = createRestTemplateWithCulledMessageConverters();
registerSlideShareInterceptor(apiKey, sharedSecret);
configureRestTemplate(this.restTemplate);
// sub apis
this.slideshowOperations = new SlideshowTemplate(this.restTemplate);
}
protected void configureRestTemplate(RestTemplate restTemplate) {
restTemplate.setErrorHandler(new SlideshareErrorHandler());
}
protected void registerSlideShareInterceptor(String apiKey, String sharedSecret) {
List<ClientHttpRequestInterceptor> interceptors = this.restTemplate.getInterceptors();
interceptors.add(new SlideShareApiValidationParameterRequestInterceptor(apiKey, sharedSecret));
this.restTemplate.setInterceptors(interceptors);
}
protected RestTemplate createRestTemplateWithCulledMessageConverters() {
// need to buffer the response in order to check the response was error or not.
// if slideshare returns error, http status is 200 and contents is error xml.
ClientHttpRequestFactory requestFactory = ClientHttpRequestFactorySelector.getRequestFactory();
ClientHttpRequestFactory bufferedRequestFactory = ClientHttpRequestFactorySelector.bufferRequests(requestFactory);
List<HttpMessageConverter<?>> messageConverters = getMessageConverters();
RestTemplate client = new RestTemplate(messageConverters);
client.setRequestFactory(bufferedRequestFactory);
return client;
}
protected List<HttpMessageConverter<?>> getMessageConverters() {
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new AllEncompassingFormHttpMessageConverter()); // for multipart upload
messageConverters.add(getXmlConverter());
return messageConverters;
}
protected HttpMessageConverter<?> getXmlConverter() {
MappingJackson2XmlHttpMessageConverter converter = new MappingJackson2XmlHttpMessageConverter();
converter.setObjectMapper(JacksonUtils.XML_MAPPER); // use shared mapper
return converter;
}
@Override
public SlideshowOperations slideshowOperations() {
return this.slideshowOperations;
}
@Override
public boolean isAuthorized() {
return false;
}
private static final class SlideShareApiValidationParameterRequestInterceptor implements
ClientHttpRequestInterceptor {
private final String apiKey;
private final String sharedSecret;
public SlideShareApiValidationParameterRequestInterceptor(String apiKey, String sharedSecret) {
this.apiKey = apiKey;
this.sharedSecret = sharedSecret;
}
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
ClientHttpRequestExecution execution) throws
IOException {
HttpRequest protectedResourceRequest = new HttpRequestDecorator(request) {
@Override
public URI getURI() {
String ts = Long.toString(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
String hash = DigestUtils.sha1Hex(sharedSecret + ts).toLowerCase();
UriComponentsBuilder builder = UriComponentsBuilder.fromUri(super.getURI());
builder.queryParam("api_key", apiKey);
builder.queryParam("ts", ts);
builder.queryParam("hash", hash);
// all params are already encoded at this point
UriComponents uriComponents = builder.build(true);
logger.debug("requesting SlideShare API: " + uriComponents.toUriString());
return uriComponents.toUri();
}
};
return execution.execute(protectedResourceRequest, body);
}
}
public RestTemplate getRestTemplate() {
return restTemplate;
}
}